# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import re
# F0401:  7,0: Unable to import 'webapp2'
# pylint: disable=F0401
import webapp2

import cache
import config
import content_processor
import content_type
import pre_cacher
import file_reader
import zip_proxy

current_config = config.DEFAULT

class MainPage(webapp2.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.write(str(current_config))

class Server(webapp2.RequestHandler):
  def get_hash_cache_key(self, rev, path):
    return '/hashes/%s/%s' % (rev, path)

  def get_file_hash(self, helper, rev, path):
    file_hash = cache.get_content(self.get_hash_cache_key(rev, path))

    if not file_hash:
      meta_cache_key = '/meta-parsed/%s' % rev
      if cache.get_content(meta_cache_key):
        return None

      meta_file_name = helper.get_meta_path(rev)
      meta_content = file_reader.read(helper, meta_file_name)
      if not meta_content:
        return None

      for line in meta_content.split('\n'):
        hash_and_path = line.split(':')
        if len(hash_and_path) == 2:
          (line_hash, line_path) = hash_and_path
          cache.set_content(self.get_hash_cache_key(rev, line_path), line_hash)
          if line_path == path:
            file_hash = line_hash
      cache.set_content(meta_cache_key, 'parsed')

    return file_hash

  def get(self, tag_type, tag, path):
    helper = config.ConfigHelper(current_config)
    content = None

    if tag_type == 'file':
      file_hash = self.get_file_hash(helper, tag, path)
      if not file_hash:
        self.abort(404)
      content = file_reader.read(helper, helper.get_hash_path(file_hash))
      if not content:
        self.abort(404)
      content = content_processor.process(path, content)

    else:
      cache_key_name = '/res/%s/%s/%s' % (tag_type, tag, path)
      content = cache.get_content(cache_key_name)
      if not content:
        if tag_type == 'rev':
          meta_file_name = helper.get_revision_path(tag)
        elif tag_type =='ver':
          meta_file_name = helper.get_version_path(tag)
        else:
          self.abort(404)

        meta_content = file_reader.read(helper, meta_file_name)
        if meta_content:
          zip_file_name = meta_content.strip(' \t\n')
        else:
          self.abort(404)

        content = zip_proxy.read(helper, zip_file_name, path)
        if not content:
          self.abort(404)
        content = content_processor.process(path, content)
        cache.set_content(cache_key_name, content)

    self.response.headers['Content-Type'] = content_type.from_path(path)
    self.response.headers['Access-Control-Allow-Origin'] = '*'
    cache_control = 'public, max-age=%d' % helper.get_max_age()
    self.response.headers['Cache-Control'] = cache_control
    self.response.body = content

class LegacyStatic(Server):
  def get(self, version, path):
    # Map x.x.x.x -> x.x.x.0 to deal with patched releases
    match = re.search('(\d+\.\d+\.\d+\.)\d+', version)
    if match:
      return super(LegacyStatic, self).get('ver', match.group(1) + '0', path)
    else:
      self.abort(404)

app = webapp2.WSGIApplication(
  [('/', MainPage),
   ('/precache_url', pre_cacher.PreCacherFromUrl),
   webapp2.Route('/serve_<tag_type>/<tag>/<path:.*>', Server),
   webapp2.Route('/static/<version>/<path:.*>', LegacyStatic)],
  debug=config.IS_DEV_APP_SERVER)
